<template>
  <div
    :class="[`${mergedClsPrefix}-split`, `${mergedClsPrefix}-split--${direction}`, themeClass]"
    :style="cssVars"
  >
    <div :class="`${mergedClsPrefix}-split-pane-1`" :style="firstPaneStyle">
      <slot name="1"></slot>
    </div>

    <div
      v-if="!disabled"
      ref="resizeTriggerElRef"
      :class="`${mergedClsPrefix}-split__resize-trigger-wrapper`"
      :style="resizeTriggerWrapperStyle"
      @mousedown="handleMouseDown"
    >
      <slot name="resize-trigger">
        <div
          :style="resizeTriggerStyle"
          :class="[
            `${mergedClsPrefix}-split__resize-trigger`,
            isDragging && `${mergedClsPrefix}-split__resize-trigger--hover`,
          ]"
        ></div>
      </slot>
    </div>

    <div :class="`${mergedClsPrefix}-split-pane-2`">
      <slot name="2"></slot>
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { ref, computed, watch } from 'vue';
  import { isNil } from 'lodash-es';

  // 定义组件属性
  interface SplitProps {
    direction?: 'horizontal' | 'vertical';
    resizeTriggerSize?: number;
    disabled?: boolean;
    defaultSize?: number;
    size?: number;
    min?: number;
    max?: number;
    onDragStart?: (e: MouseEvent) => void;
    onDragMove?: (e: MouseEvent) => void;
    onDragEnd?: (e: MouseEvent) => void;
    'onUpdate:size'?: (size: number) => void;
    onUpdateSize?: (size: number) => void;
    watchProps?: string[];
  }

  const props = withDefaults(defineProps<SplitProps>(), {
    direction: 'horizontal',
    resizeTriggerSize: 3,
    disabled: false,
    defaultSize: 0.5,
    min: 0,
    max: 1,
  });

  // 定义事件
  const emit = defineEmits<{
    (e: 'update:size', size: number): void;
    (e: 'drag-start', e: MouseEvent): void;
    (e: 'drag-move', e: MouseEvent): void;
    (e: 'drag-end', e: MouseEvent): void;
  }>();

  // 响应式数据
  const resizeTriggerElRef = ref<HTMLElement | null>(null);
  const isDragging = ref(false);
  const offset = ref(0);
  const internalSize = ref(props.defaultSize);
  const mergedClsPrefix = ref('n'); // 默认使用 naive-ui 的前缀

  // 计算属性
  const sizeRef = computed(() => (isNil(props.size) ? internalSize.value : props.size));

  // CSS 变量
  const cssVars = computed(() => {
    return {
      '--n-bezier': 'cubic-bezier(0.4, 0, 0.2, 1)',
      '--n-resize-trigger-color': '#d0d0d0',
      '--n-resize-trigger-color-hover': '#18a058',
    };
  });

  // 主题类名
  const themeClass = computed(() => {
    return '';
  });

  const firstPaneStyle = computed(() => {
    const size = sizeRef.value * 100;
    return {
      flex: `0 0 calc(${size}% - ${(props.resizeTriggerSize * size) / 100}px)`,
    };
  });

  const resizeTriggerStyle = computed(() => {
    return props.direction === 'horizontal'
      ? {
          width: `${props.resizeTriggerSize}px`,
          height: '100%',
        }
      : {
          width: '100%',
          height: `${props.resizeTriggerSize}px`,
        };
  });

  const resizeTriggerWrapperStyle = computed(() => {
    const isHorizontal = props.direction === 'horizontal';
    return {
      width: isHorizontal ? `${props.resizeTriggerSize}px` : '',
      height: isHorizontal ? '' : `${props.resizeTriggerSize}px`,
      cursor: isHorizontal ? 'col-resize' : 'row-resize',
    };
  });

  // 监听默认大小变化
  if (props.watchProps?.includes('defaultSize')) {
    watch(
      () => props.defaultSize,
      (newVal) => {
        internalSize.value = newVal;
      }
    );
  }

  // 处理鼠标按下事件
  const handleMouseDown = (e: MouseEvent) => {
    e.preventDefault();

    if (props.disabled) return;

    isDragging.value = true;
    emit('drag-start', e);

    // 触发更新事件
    if (props.onDragStart) {
      props.onDragStart(e);
    }

    const handleMouseMove = (moveEvent: MouseEvent) => {
      handleMouseMoveEvent(moveEvent);
      emit('drag-move', moveEvent);
      if (props.onDragMove) {
        props.onDragMove(moveEvent);
      }
    };

    const handleMouseUp = () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
      isDragging.value = false;
      emit('drag-end', e);
      if (props.onDragEnd) {
        props.onDragEnd(e);
      }
      document.body.style.cursor = '';
    };

    document.body.style.cursor = resizeTriggerWrapperStyle.value.cursor || '';
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);

    // 计算偏移量
    const triggerEl = resizeTriggerElRef.value;
    if (triggerEl) {
      const rect = triggerEl.getBoundingClientRect();
      offset.value =
        props.direction === 'horizontal' ? e.clientX - rect.left : rect.top - e.clientY;
    }

    handleMouseMoveEvent(e);
  };

  // 处理鼠标移动事件
  const handleMouseMoveEvent = (e: MouseEvent) => {
    const triggerEl = resizeTriggerElRef.value;
    const parentEl = triggerEl?.parentElement;

    if (!parentEl) return;

    const parentRect = parentEl.getBoundingClientRect();

    if (!parentRect) return;

    let sizeRatio: number;

    if (props.direction === 'horizontal') {
      sizeRatio =
        (e.clientX - parentRect.left - offset.value) / (parentRect.width - props.resizeTriggerSize);
    } else {
      sizeRatio =
        (e.clientY - parentRect.top + offset.value) / (parentRect.height - props.resizeTriggerSize);
    }

    // 应用最小值和最大值限制
    let clampedSize = sizeRatio;
    if (props.min) {
      clampedSize = Math.max(sizeRatio, props.min);
    }
    if (props.max) {
      clampedSize = Math.min(clampedSize, props.max);
    }

    // 更新大小
    updateSize(clampedSize);
  };

  // 更新大小
  const updateSize = (newSize: number) => {
    // 替换 call 函数的使用，直接调用函数
    if (props.onUpdateSize) {
      props.onUpdateSize(newSize);
    }

    emit('update:size', newSize);

    if (isNil(props.size)) {
      internalSize.value = newSize;
    }
  };

  // 暴露方法给父组件
  defineExpose({
    resizeTriggerElRef,
  });
</script>

<style scoped>
  .n-split {
    display: flex;
    width: 100%;
    height: 100%;
  }

  .n-split--horizontal {
    flex-direction: row;
  }

  .n-split--vertical {
    flex-direction: column;
  }

  .n-split-pane-1 {
    overflow: hidden;
  }

  .n-split-pane-2 {
    overflow: hidden;
    flex: 1;
  }

  .n-split__resize-trigger-wrapper {
    /* 根据需要添加样式 */
  }

  .n-split__resize-trigger {
    background-color: var(--n-resize-trigger-color);
    transition: background-color 0.3s var(--n-bezier);
  }

  .n-split__resize-trigger:hover,
  .n-split__resize-trigger--hover {
    background-color: var(--n-resize-trigger-color-hover);
  }
</style>